and Editing Forms

distinguishes databases and forms. A database is an array of unformatted data, while the form specifies the structure of the data and describes how to display it in a card. The standard user interface that comes up when is started deals with database presentation and modification; to edit the presentation, or to create a new database, start the form editor from the File pulldown in the main window.

The form editor is a separate window that is rather more complicated than the standard database user interface. It is basically a simple UI builder that allows the user to create and position UI elements in a card.

Setup

The first step when creating a new database is choosing a form name. This is the name that will appear in the Database pulldown in the main window (actually, the pulldown should be called Form, but I fear that would confuse casual users). Every form references a database whose contents it presents; this name must also be chosen. Typically, both names are the same.

Both the form name and database names are also the file names the form and the database will be stored in. The form name gets the extension ``.gf'', and non-procedural databases get the extension ``.db'' tacked on if the names are not fully qualified (i.e., do not begin with ``/'' or ``∼''). If the database is procedural, the database file is a script, and has no .db or any other extension. This script is executed to read or write data.

When a database or form is read, the path it was read from is stored; when the database or form is changed, it is written back to that path. When a new database is created, and its name does not begin with ``/'' or ``∼'' as defined in the second line of the form editor, it is stored in the same directory as its form file. The default is always ∼/.grok. The Help →Database popup shows which paths are actually used.

The database is a two-dimensional array of strings. The rows are called cards, and the columns are called fields. Rows are separated by newlines, and columns are separated by the field delimiter. The field delimiter is a colon by default, but can be changed to any character. The button accepts characters, octal constants \nnn, and the tab character \t. Any character other than \0 and newline can be chosen; will properly escape the character when it appears in a database string. Severe chaos may result if the delimiter character is changed when the database already contains data.

Databases can be marked read-only. A user accessing a database through a form that is has the read-only flag set will not be able to change any cards, and will not be able to write back.

A procedural database does not read a file, but calls a script that provides the data in the same format that the file would contain. If the procedural button is turned on, the referenced database name is the name of the script, not of any database file. It may contain options. When the database is read, appends the option "-r" (read) and the form name as shown in the Form name button (without prepending a path or appending an extension). When writing, -w is appended instead of -r. The script must print the data to stdout if -r is specified, or must accept the data from stdin if -w is specified, separating columns with the field delimiter character and separating rows with newlines. If the delimiter or newlines appear in as part of a data string, it must be escaped with a backslash.

A comment can be specified that should give the name of the author of the form, or special caveats. The comment is displayed only in the form editor window.

a Card

After the general setup is done, fields can be arranged on a card ``canvas'', which has the same size and layout as the final card will have, but doesn't look as nice and shows extra information. Fields appear as blue rectangular boxes, some of which are divided in the middle (depending on the field type). The current field, whose specification is displayed in the form editor window. A field can be moved by left-clicking somewhere inside the field (but not too close to an edge) and dragging. The size can be changed by dragging one of the four edges, and the divider can also be dragged. Fields should not overlap. The card canvas can be resized; fields should not overlap the canvas window edges.

The canvas is divided in two parts by a horizontal fat line. The divider can be moved vertically by dragging the little square that initially appears near the top right corner of the canvas. Everything above the divider is the static part; everything below the divider is the card part. The card part displays one row of the database if one is selected; this information changes frequently whenever a search is performed or a row is chosen from the summary.

The static part does not normally change, it is intended for static data such as the average of all fields, a chart displaying statistics, or buttons. This part is not entirely static because entering new cards or resorting the database may change data, but it is not bound to a particular card, and it remains accessible if no card is chosen. This makes it a good place to place form switch buttons that would otherwise become unavailable when no card is displayed.

There are several types of fields. Not all of them store data in the database; some are decorative or display computed information.

=2cm Input This is the main type of field. It displays an editable (unless turned off) string in the database, along with a label. Input fields should not be put into the static part of the canvas.

Time A variation of the Input field. The database representation is a number of seconds. It is displayed as a date, as a time, as both date and time, and as a duration. The first three assume the database string to be a number of seconds since January 1, 1970; the last simply assumes a number of seconds up to 86399 (one day minus 1 second). When a string is entered into a Time field, it is converted to the numeric representation, reformatted, and reprinted. Time fields are useful because they can be used in expressions for calculation; expressions always see the numeric database string. Time fields should not be put into the static part of the canvas.

Note A note is a multi-line Input field. It should be used only for multiline text input because it cannot be tabbed over, and because pressing Return when entering data into the card into a Note actually inserts a newline, rather than skipping to the next field as an Input-type field would. Note fields should not be put into the static part of the canvas.

Choice Unlike all other types, many choice fields reference the same database string. They all must have the same summary column, the same database column, and the same internal field name (these three are buttons in the form editor). They differ only in the Choice/flag code. always makes sure that only one of the choice fields with identical internal field names can be active at any time; the database string then matches the Choice/flag code of that field. Most attributes of a Choice item, when changed, are copied to all other Choice items that have the same internal name. Choice fields should not be put into the static part of the canvas.

Label Labels are purely decorative. They print an arbitrary one-line string at a position in the card. There is no associated database string. Labels are rarely needed because most of the other types come with their own built-in label parts. The label is static, expressions cannot be used.

Print Print fields are like Input fields, but no text can be entered. Unlike labels, they can display an expression specified in the Input Default button of the form editor. This can be used to display a running average or sum in cards, or display other computed information. There is no associated database string. Print fields are useful in both the static and card parts of the canvas.

Flag Flags are boolean database strings: the string either matches the predefined string (true), or it is empty (false). (In fact, a string that doesn't match is also considered false, but this is not part of the normal operation.) The string that constitutes true is specified with the Choice/flag code button in the form editor.

Button Buttons have an associated action expression that is executed when the button is pressed. This action could start a shell script, for example. Buttons are not associated with any database string, but the expression can access one. For example, a database of demo programs can have a button that executes the program. The returned string is executed, there is no need to use the system keyword unless nesting is desired. Note that the action expression is the only type of expression that may contain switch statements; see the Expression Grammar chapter for details. It is often a good idea to put buttons in the static part of the canvas.

Chart Charts display data as bar or line charts. The X axis is divided into one slot per row in the database; the Y axis depends on the values computed from those rows (X and Y may be exchanged). Each chart contains one or more components. A component computes values that is plotted in the chart; a chart may display more than one value. For example, an expense account chart may display a stacked bar chart consisting of different color-coded types of costs, each described by a component. There are many variations for configuring charts and their components. Charts should be put into the static part of the canvas.

=2em Each field has a number of parameters that depend on the type. The most important is the internal field name. It must be unique, except for choice fields which are grouped by assigning common internal field names. If the field references a database string, the internal field name also names the database string. The internal field name can be used in expressions to read the database string. For example, suppose you have a database of backup tapes, you may have an Input field with an internal field name capacity, and another Input field named used. You could then add a Print field whose Input Default expression is (_capacity - _used). The Print field then displays the remaining free space on each tape, even though the database only contains total capacity and used capacity. Another Print label may have an expression (sum(_used)), which displays a running total of all tapes' contents. sum is one of a group of functions that loop over all cards rather than just referencing the current card; see the Expression Grammar chapter for details. It is also possible to reference a database field for which there is no field description in an expression; in this case, the field is referenced by number. Fields in the database are numbered left to right, beginning with 0.

The next button in the form editor is the database column. It needs to be specified only for field types that display the column and allow entry into the column. These fields are ``windows'' into the database; there is normally one field for each database column. All fields that do not reference a database column are merely decoration, no change of the database is possible through such a decorative field (although the decorative field may read the database, as Print fields do). This relation between fields and database columns also serves to give a symbolic name to database columns; these symbolic names can be used in expressions by prefixing them with an underscore. (It is also possible to use the column number in expressions, but that is less convenient).

The main window has three parts, a summary, the static area, and the card. The summary contains one line per card, while the card contains the entire card's information as defined with the form editor and the card canvas. The static part is optional and programmed in the same way as the card. The Summary column and Width in summary buttons in the form editor determine which fields also appear in the summary; this is a subset of the fields that reference a database column (decoration fields can not be put into the summary). The two buttons specify the order in database column and the width in characters. Two blanks are inserted between fields in the summary automatically. The summary has a title; it can not be specified directly but is taken from the Label text of the field.

Here is a brief summary of all buttons in the form editor that specify a field in the card:

=5cm


Field type The type of a field is entered here. See above for a list of available types and what they do.

Searchable The main window contains a Search input button. It searches through all cards and puts all cards containing the search string into the summary. Fields that are not searchable are excluded from the search.

Read only The user cannot change the database string referenced by a field that is read-only. This is useful if there are two forms referencing the same database, one for you and one for the unwashed masses with lots of read-only flags set. The read-only flag can also be set for the entire database with the button near the top of the form editor window; setting that flag overrides all field read-only flags.

Not sortable The field will be omitted from the Sort pulldown in the main menu.

Default sort When the file is read in from disk, it is sorted by the field that has this flag on. Setting it in any field will clear the Default sort flag in all other items automatically. If no field has the Default sort flag, the file will not be sorted when it is read. It is possible but not recommended to have both the Default sort flag and the Not sortable flag on in the same field.

Internal field name All fields have an unique name. Choice names are not unique, choice fields are grouped by a common name. If the field references a database string, the internal field name also names the database column, which can then be accessed in expressions symbolically.

Database column If the field references a database column, this button says which one, 0 being the first column. If not, this button is grayed out. The column number must be unique, except for choice fields which are grouped by a common database column (and a common internal field name, too).

Width in summary If the width is nonzero, the database string referenced by the field will appear in the summary, with as many characters as specified. Two blanks are appended. The summary always uses monospaced Courier to make columns line up vertically.

Summary column If the width is nonzero, this value specifies the order of fields in summary lines. No two fields may have the same summary column number, but there may be gaps.

Choice/flag code The string that Flag and Choice fields store in the database, if active. No two Choice fields with the same internal name may have the same code.

Shown as If this string is set, it will be displayed in the summary in place of the choice/flag code. Basically, it is a mnemonic name for the choice/flag code that a user can understand.

Time format Time fields have four different formats, as described above. The format controls what gets printed into the card, and how user input is interpreted.

Label text All field types come with some kind of text string that is printed into the field in the card. This string is always literal, it cannot be an expression.

Label justification Labels can be centered, left-aligned, or right-aligned. This is not shown in the card canvas, press the Preview button to see the effect.

Label font The font used for the label. Five fonts are available.

Max input length The maximum number of characters than can be entered into an Input, Time, or Note field. The default is 100 for Input and Time fields, and 10000 for Note fields. Always make sure that note fields have a sufficient maximum length. This number is passed to the Motif widget to limit input length, but does not lead to increased memory usage for the database.

Input default For Input, Time, Flag, and Choice fields, this field provides the defaults when a new card is added to the database. It can be an expression. For Print fields, the Input default specifies what gets printed into the inset area of the field; input default is actually a misnomer because Print field texts cannot be input and are evaluated whenever the database changes, not just when a new card is added. In general, Choice fields should always have a default. If the field has type Time, the input default expression should evaluate to a number of seconds, not to a string containing a date. For example, to make the Time field default to today, use (date), not date.

Input justification Input can be centered, left-aligned, or right-aligned. This is not shown in the card canvas, press the Preview button to see the effect.

Input font The font used for the input area. Five fonts are available. It is recommended to use Courier for Note fields (and, by extension, for Input and Time fields) because printing functions print notes using a fixed-width font.

Grayed out if If the named expression evaluates to true, the field is grayed out and cannot be used to alter the database. The expression is evaluated every time the database changes.

Invisible if If the named expression evaluates to true, the field is excluded from the card. The expression is evaluated only once, when the database is read from disk. This can be used to hide entries if the wrong user has read the database. Invisibility does not affect the summary.

Read-only if If the named expression evaluates to true, the field is read-only. The expression is evaluated only once, when the database is read from disk.

Skip if Normally, pressing Return in an Input or Time field advances the cursor to the next field (fields are ordered by their bottom left corner, in Y-major order). If the named expression of the next field evaluates to true, the field is skipped and the cursor is put elsewhere. This expression is evaluated every time return is pressed in the previous field. A constant expression such as true is also useful.

Action when pressed If the button is pressed, this expression is evaluated. The result is ignored. Typically, the expression is the name of a shell script. The expression may use the switch statement, which switches to another database and/or performs a query on all cards.

Chart flags Not documented yet. This part of the menu is still under development. =2em


Some of the above accept expressions. An expression begins with a parenthesis, a brace, or a dollar sign. Everything else is a literal string. Parentheses and braces are numeric and string expressions, respectively; a dollar sign followed by an environment variable is a shortcut for the same sequence enclosed in braces. The system statement should be used sparingly, because some expressions (such as the grayed-out-if expression) are evaluated frequently. See the Expression Grammar section for details.

There is a row of buttons in the form editor for various operations:

=2.5cm Queries Starts up a window that allows entry of standard queries, as name/expression pairs. The name is what will appear in the Query pulldown in the main menu; the expression is what gets executed if the name is selected in the pulldown. When a name is selected, the expression is applied to all cards in the database, and those that return true are put into the summary. For example, assuming your database has an Input field with the internal name value, the query expression (_value avg(_value)) will select all cards whose value is above average.One of the queries can be selected as the default query that will be performed when the database is read from disk.

Def Help The main window has a help button in the lower left corner. This button pops up a help window with some generic info about . With the Def Help button, more text can be entered that will be appended to the generic help text. The text should explain the card, how to use it, and what the fields mean.

Debug This button checks the consistency of all fields, and reports conflicts such as non-unique internal names or redundant choice flags. At this time, expressions are not checked. If the Debug button reportrs nothing, the no problems were found. The Done button always does a debugging run first, and refuses to exit if errors were found.

Preview The card canvas shows the layout of fields in the card, as boxes that show additional information such as type, database column, flag/choice code, and summary column. This does not reflect the final card that the user will see very well; in particular, whether a label string fits into the field on the card canvas does not mean that the same label will fit into the final card. Preview shows precisely what the card will look like.

Help Print general help information.

Cancel Discards all operations done with the form editor since it was installed, and removes the form editor window after asking for confirmation.

Done Check all fields for consistency. If no problems are found, the form file is written. The file name is taken from the Form name button at the top of the form, with ∼/.grok prepended and .gf appended if appropriate.

Add Adds a new field to the card. Its type, parameters, and position on the card canvas are chosen based on the currently selected card, so it's a good idea to select a field that is similar to the new one before pressing Add. If the card canvas has no free space below the bottom field, the new field may be placed under the bottom field where it can't be seen; it is generally a good idea to start with a card canvas that is too large and resize it to the correct size after all fields have been added and positioned.

Delete Delete the currently selected field. There is no Undo function to get it back. =2em